package com.gyg.threadPool;

import com.google.common.util.concurrent.ThreadFactoryBuilder;
import lombok.extern.slf4j.Slf4j;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.*;

/**
 * ThreadPoolExecutor
 */
@Slf4j
public class ThreadPoolExecutorTest {
    /**
     * 核心线程数
     */
    private static final int CORE_POOL_SIZE = 5;
    /**
     * 最大线程数
     */
    private static final int MAX_POOL_SIZE = 10;
    /**
     * 保持连接时间
     */
    private static final long KEEP_ALIVE_TIME = 1;
    /**
     * 队列长度
     */
    private static final int QUEUE_CAPACITY = 100;
    /**
     * 时间单位
     */
    private static final TimeUnit TIME_UNIT = TimeUnit.SECONDS;

    public static ThreadPoolExecutor createThreadPoolExecutor() {
        //利用guava：创建一个线程工程，用于线程池命名
        ThreadFactory threadFactory = new ThreadFactoryBuilder()
                .setNameFormat("MyThreadPool" + "-%d")
                .setDaemon(true).build();

        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(CORE_POOL_SIZE,
                MAX_POOL_SIZE,
                KEEP_ALIVE_TIME,
                TIME_UNIT,
                new ArrayBlockingQueue<>(QUEUE_CAPACITY),
                threadFactory,
                new ThreadPoolExecutor.CallerRunsPolicy());

        return threadPoolExecutor;
    }

    public static void main(String[] args) {
        //submit方法
        //submitMethod();
        //invokeAll方法
        //invokeAllMethod();
        //invokeAny方法
        invokeAnyMethod();
        //shutDown方法
        //shutDownMethod();
    }

    /**
     * <T> Future<T> submit(Callable<T> task);
     */
    public static void submitMethod() {
        ThreadPoolExecutor service = createThreadPoolExecutor();
        //通过submit提交任务
        Future<String> future = service.submit(() -> {
            log.info("Runing...");
            Thread.sleep(1000);
            return "OK";
        });

        try {
            //通过get方法获取返回值
            String str = future.get();
            log.info(str);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
     */
    public static void invokeAllMethod() {
        ThreadPoolExecutor service = createThreadPoolExecutor();
        try {
            //提交一个任务集合，接收返回状态的集合
            List<Future<String>> futureList = service.invokeAll(Arrays.asList(
                    //任务1
                    () -> {
                        log.info("begin1...");
                        Thread.sleep(1000);
                        return "1";
                    },
                    //任务2
                    () -> {
                        log.info("begin2...");
                        Thread.sleep(500);
                        return "2";
                    },
                    //任务3
                    () -> {
                        log.info("begin3...");
                        Thread.sleep(2000);
                        return "3";
                    }));
            //遍历返回值集合
            futureList.forEach(f -> {
                try {
                    log.info(f.get());
                } catch (InterruptedException | ExecutionException e) {
                    e.printStackTrace();
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * <T> T invokeAny(Collection<? extends Callable<T>> tasks)
     */
    public static void invokeAnyMethod() {
        ThreadPoolExecutor service = createThreadPoolExecutor();
        try {
            //提交一个任务集合，接收最先执行完的任务的返回结果，其他任务的结果不接收，且不继续执行
            String result = service.invokeAny(Arrays.asList(
                    //任务1
                    () -> {
                        log.info("begin1...");
                        Thread.sleep(1000);
                        log.info("end1...");
                        return "1";
                    },
                    //任务2
                    () -> {
                        log.info("begin2...");
                        Thread.sleep(500);
                        log.info("end2...");
                        return "2";
                    },
                    //任务3
                    () -> {
                        log.info("begin3...");
                        Thread.sleep(2000);
                        log.info("end3...");
                        return "3";
                    }));
            //输出返回值
            log.info(result);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * void shutdown();
     */
    public static void shutDownMethod() {
        ThreadPoolExecutor service = createThreadPoolExecutor();
        Future<?> future1 = service.submit(() -> {
            try {
                log.info("thread 1 run...");
                Thread.sleep(500);
                log.info("thread 1 end...");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        Future<?> future2 = service.submit(() -> {
            try {
                log.info("thread 2 run...");
                Thread.sleep(1000);
                log.info("thread 2 end...");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        Future<?> future3 = service.submit(() -> {
            try {
                log.info("thread 3 run...");
                Thread.sleep(2000);
                log.info("thread 3 end...");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        //线程停止
        log.info("shutDown执行");
        //service.shutdown();
        log.info(Thread.currentThread().getName());
        try {
            //主线程休眠一秒后执行shutdownNow
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        service.shutdownNow();

        //线程调用shutdown方法后再提交的任务不会被执行
        Future<?> future4 = service.submit(() -> {
            try {
                log.info("thread 4 run...");
                Thread.sleep(500);
                log.info("thread 4 end...");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
    }
        
}
